import { _decorator, Component, EventTouch, Input, instantiate, Node, Sprite, Vec3 } from 'cc';
import { BaseComponent } from '../../../Manager/UIManager/BaseComponent';
import { DIRECTION, GAME_PREFAB, GAME_TOP, GlobalData } from '../../../Data/GlobalData';
import { SingleBrick } from './SingleBrick';
import { GameScene } from '../GameScene';
const { ccclass, property } = _decorator;

@ccclass('ClearLoad')
/**
 * 消除层
 */
export class ClearLoad extends BaseComponent {

    //消除砖块数组
    private BricksArray: Node[][] = [];

    //背景层
    @property(Node)
    private BgLoad: Node = null;

    //元素层
    @property(Node)
    private BrickLoad: Node = null;

    //创建起始位置
    private StartPos: Vec3 = new Vec3(0, 0, 0);

    //砖块类型数组
    private BrickTypeArray: number[] = [];

    //提示方块数组（需要随机比较大的提醒不用返回boolean，通过数组来随机提醒）
    private TipArray: Node[] = [];

    //消除方块数组
    private ClearBrickArray: Node[] = [];
    //相同使用砖块
    private SameBrickArray: Node[] = [];

    //第一个点击的砖块
    private FirstClickBrick: Node = null;
    //第二个点击的砖块
    private SecondClickBrick: Node = null;

    //游戏场景
    @property(Node)
    private GameScene: Node = null;

    protected Init(): void {
        this.StartPos = new Vec3(
            -375 + (750 - GlobalData.HorNum * GlobalData.BrickSpace) / 2 + GlobalData.BrickSpace / 2,
            -300 + (600 - GlobalData.VerNum * GlobalData.BrickSpace) / 2 + GlobalData.BrickSpace / 2,
            0
        )
        this.CreateBg();
    }

    protected OnShow(): void {
        this.BrickTypeArray = [];
        this.RandomBrick();

    }

    /**
     * 创建背景
     */
    private CreateBg() {
        for (let i = 0; i < GlobalData.HorNum; i++) {
            let sbs: Node[] = [];
            for (let j = 0; j < GlobalData.VerNum; j++) {
                let bg: Node = new Node();
                bg.setParent(this.BgLoad);
                let bg_sprite: Sprite = bg.addComponent(Sprite);
                bg_sprite.spriteFrame = app.resManager.SpriteFrames["game_brickbg"];
                bg.setPosition(new Vec3(this.StartPos.x + i * GlobalData.BrickSpace, this.StartPos.y + j * GlobalData.BrickSpace, 0));

                let sb: Node = instantiate(app.resManager.Prefabs[GAME_PREFAB.SINGLEBRICK]);
                sb.setParent(this.BrickLoad);
                sb.setPosition(new Vec3(this.StartPos.x + i * GlobalData.BrickSpace, this.StartPos.y + j * GlobalData.BrickSpace, 0));
                sb.getComponent(SingleBrick).UpdateMyId(i, j);
                sb.on(Input.EventType.TOUCH_START, this.BrickClick, this);

                sbs.push(sb);
            }
            this.BricksArray.push(sbs);
        }
    }

    /**
     * 砖块点击
     */
    private BrickClick(_e: EventTouch) {
        if (this.FirstClickBrick) {//判断点击的两个砖块是否能够交换
            this.SecondClickBrick = _e.currentTarget;

            //判断是否是相邻的
            let hor0: number = this.FirstClickBrick.getComponent(SingleBrick).BrickInfo.HorId;
            let ver0: number = this.FirstClickBrick.getComponent(SingleBrick).BrickInfo.VerId;

            let hor1: number = this.SecondClickBrick.getComponent(SingleBrick).BrickInfo.HorId;
            let ver1: number = this.SecondClickBrick.getComponent(SingleBrick).BrickInfo.VerId;

            if ((Math.abs(hor0 - hor1) == 1 && ver0 == ver1) || (Math.abs(ver0 - ver1) == 1 && hor0 == hor1)) {

                this.FirstClickBrick.getComponent(SingleBrick).ChangePos(this.SecondClickBrick.getComponent(SingleBrick).BrickInfo);
                this.SecondClickBrick.getComponent(SingleBrick).ChangePos(this.FirstClickBrick.getComponent(SingleBrick).BrickInfo);

                this.FirstClickBrick.getComponent(SingleBrick).IamUnChoose();

                app.topManager.ShowTop(GAME_TOP.NOTOUCH, false);
                this.scheduleOnce(() => {
                    this.CheckThree();
                }, GlobalData.BrickMoveTime + 0.1)

            } else {
                this.FirstClickBrick.getComponent(SingleBrick).IamUnChoose();
                this.FirstClickBrick = null;
            }

        } else {
            this.FirstClickBrick = _e.currentTarget;
            this.FirstClickBrick.getComponent(SingleBrick).IamChoose();
        }

    }


    /**
     * 随机分布
     */
    private RandomBrick() {

        app.logManager.warn("随机分布")

        for (let i = 0; i < this.BricksArray.length; i++) {
            for (let j = 0; j < this.BricksArray[i].length; j++) {

                this.BrickTypeArray = [];

                for (let i = 0; i < GlobalData.BrickTypeNum; i++)this.BrickTypeArray.push(i);

                if (i >= 2) {//横向判断不能有相同得
                    if (this.BricksArray[i - 2][j].getComponent(SingleBrick).BrickInfo.ClearIndex == this.BricksArray[i - 1][j].getComponent(SingleBrick).BrickInfo.ClearIndex) {
                        this.BrickTypeArray.splice(this.BrickTypeArray.indexOf(this.BricksArray[i - 2][j].getComponent(SingleBrick).BrickInfo.ClearIndex), 1)
                    }
                }

                if (j >= 2) {//纵向判断不能有相同得
                    if (this.BricksArray[i][j - 2].getComponent(SingleBrick).BrickInfo.ClearIndex == this.BricksArray[i][j - 1].getComponent(SingleBrick).BrickInfo.ClearIndex) {
                        this.BrickTypeArray.splice(this.BrickTypeArray.indexOf(this.BricksArray[i][j - 2].getComponent(SingleBrick).BrickInfo.ClearIndex), 1)
                    }
                }

                this.BricksArray[i][j].getComponent(SingleBrick).UpdateClearIndex(this.BrickTypeArray[Math.floor(Math.random() * this.BrickTypeArray.length)]);

            }
        }

        this.CheckCanClear();
    }

    /**
     * 判断三个相连
     */
    private CheckThree() {
        this.ClearBrickArray = [];
        for (let i = 0; i < this.BricksArray.length; i++) {
            for (let j = 0; j < this.BricksArray[i].length; j++) {
                this.VerClear(this.BricksArray[i][j]);
                this.HorClear(this.BricksArray[i][j]);
            }
        }

        console.log(this.ClearBrickArray, "可以消除的元素么")

        if (this.ClearBrickArray.length > 0) {

            for (let cb of this.ClearBrickArray) {

                this.GameScene.getComponent(GameScene).AddBullet(
                    {
                        Style: cb.getComponent(SingleBrick).BrickInfo.ClearIndex,
                        Num: 1
                    }
                )

                cb.getComponent(SingleBrick).BrickInfo.ClearIndex = -1;
            }

            let check_hor: number[] = [];
            for (let cb of this.ClearBrickArray) {
                if (check_hor.indexOf(cb.getComponent(SingleBrick).BrickInfo.HorId) == -1) {
                    check_hor.push(cb.getComponent(SingleBrick).BrickInfo.HorId);
                }
            }

            for (let hor of check_hor) {
                this.CheckPlayDown(hor)
            }

            check_hor = [];

            this.scheduleOnce(() => {
                this.CheckThree();
            }, GlobalData.BrickDownSpeed + 0.1)

        } else {
            app.topManager.ShowTop(GAME_TOP.NOTOUCH, false);
            if (this.FirstClickBrick) this.FirstClickBrick.getComponent(SingleBrick).RevertPos();
            if (this.SecondClickBrick) this.SecondClickBrick.getComponent(SingleBrick).RevertPos();

            this.scheduleOnce(() => {
                app.topManager.HideTop(GAME_TOP.NOTOUCH);
            }, GlobalData.BrickMoveTime + 0.1)
        }

        this.FirstClickBrick = null;
        this.SecondClickBrick = null;
    }
    /**
     * 横向判断消失
     */
    private HorClear(_brick: Node) {
        let hor: number = _brick.getComponent(SingleBrick).BrickInfo.HorId;
        let ver: number = _brick.getComponent(SingleBrick).BrickInfo.VerId;
        let clear_index: number = _brick.getComponent(SingleBrick).BrickInfo.ClearIndex;

        this.SameBrickArray = [];

        for (let i = hor; i < GlobalData.HorNum; i++) {
            if (this.BricksArray[i][ver].getComponent(SingleBrick).BrickInfo.ClearIndex == clear_index) {
                this.SameBrickArray.push(this.BricksArray[i][ver]);
            } else {
                break;
            }
        };

        if (this.SameBrickArray.length > 2) {

            for (let sb of this.SameBrickArray) {
                if (this.ClearBrickArray.indexOf(sb) == -1) {
                    this.ClearBrickArray.push(sb);
                }
            }

        }

    }

    /**
     * 纵向判断消失
     */
    private VerClear(_brick: Node) {
        let hor: number = _brick.getComponent(SingleBrick).BrickInfo.HorId;
        let ver: number = _brick.getComponent(SingleBrick).BrickInfo.VerId;
        let clear_index: number = _brick.getComponent(SingleBrick).BrickInfo.ClearIndex;

        this.SameBrickArray = [];

        for (let i = ver; i < GlobalData.VerNum; i++) {
            if (this.BricksArray[hor][i].getComponent(SingleBrick).BrickInfo.ClearIndex == clear_index) {
                this.SameBrickArray.push(this.BricksArray[hor][i]);
            } else {
                break;
            }
        }

        if (this.SameBrickArray.length > 2) {
            for (let sb of this.SameBrickArray) {
                if (this.ClearBrickArray.indexOf(sb) == -1) {
                    this.ClearBrickArray.push(sb);
                }
            }
        }
    }

    /**
     * 判断播放下降动画
     */
    private CheckPlayDown(_hor: number) {
        let hor: number = _hor;
        let ver: number = -1;
        let clear_num: number = 0;

        console.log("检查的位置", hor, ver)

        for (let i = 0; i < GlobalData.VerNum; i++) {//判断这一类消失了多少个
            if (this.BricksArray[hor][i].getComponent(SingleBrick).BrickInfo.ClearIndex == -1) {
                if (ver == -1) ver = i;

                //在这里判断我的下降数量  有Bug

                clear_num++;
            }
        }
        console.log("这列消失的个数", clear_num);

        for (let i = ver; i < GlobalData.VerNum; i++) {//
            this.BricksArray[hor][i].getComponent(SingleBrick).PlayDownAni(clear_num);
            if (i + clear_num > GlobalData.VerNum - 1) {
                this.BricksArray[hor][i].getComponent(SingleBrick).UpdateClearIndex(Math.floor(Math.random() * GlobalData.BrickTypeNum));
            } else {
                console.log(i + clear_num, this.BricksArray[hor][i + clear_num].getComponent(SingleBrick).BrickInfo)
                this.BricksArray[hor][i].getComponent(SingleBrick).UpdateClearIndex(this.BricksArray[hor][i + clear_num].getComponent(SingleBrick).BrickInfo.ClearIndex);
            }
        }


    }

    /**
     * 判断是否有可以相连得 两种情况1、两个相邻得是一样得。2、隔一个得两个是一样得
     */
    private CheckCanClear() {

        for (let i = 0; i < this.BricksArray.length; i++) {
            for (let j = 0; j < this.BricksArray[i].length; j++) {
                if (this.CheckHor0(this.BricksArray[i][j])) { return; }
                if (this.CheckHor1(this.BricksArray[i][j])) { return; }
                if (this.CheckVer0(this.BricksArray[i][j])) { return; }
                if (this.CheckVer1(this.BricksArray[i][j])) { return; }
            }
        }

        this.RandomBrick();
    }

    /**
     * 横向判断第一种情况
     * 如果横向得是一样得，判断左侧或者右侧得周围是否有相同得
     */
    private CheckHor0(_brick: Node): boolean {

        let hor: number = _brick.getComponent(SingleBrick).BrickInfo.HorId;
        let ver: number = _brick.getComponent(SingleBrick).BrickInfo.VerId;
        let clear_index: number = _brick.getComponent(SingleBrick).BrickInfo.ClearIndex;

        let left: number = hor - 1;
        let right: number = hor + 2;

        if (this.ReturnClearIndex(hor + 1, ver) == clear_index) {//横向两个相同得了

            //判断左侧周边有没有
            if (this.ReturnClearIndex(left - 1, ver) == clear_index) {
                this.TipArray.push(this.BricksArray[left - 1][ver]);
                return true;
            }
            if (this.ReturnClearIndex(left, ver - 1) == clear_index) {
                this.TipArray.push(this.BricksArray[left][ver - 1]);
                return true
            };
            if (this.ReturnClearIndex(left, ver + 1) == clear_index) {
                this.TipArray.push(this.BricksArray[left][ver + 1]);
                return true;
            }

            //判断右侧周边有没有
            if (this.ReturnClearIndex(right + 1, ver) == clear_index) {
                this.TipArray.push(this.BricksArray[right + 1][ver]);
                return true;
            }
            if (this.ReturnClearIndex(right, ver - 1) == clear_index) {
                this.TipArray.push(this.BricksArray[right][ver - 1]);
                return true;
            }
            if (this.ReturnClearIndex(right, ver + 1) == clear_index) {
                this.TipArray.push(this.BricksArray[right][ver + 1]);
                return true;
            }

            return false;
        }
    }

    /**
     * 横向判断得第二种
     */
    private CheckHor1(_brick: Node): boolean {

        let hor: number = _brick.getComponent(SingleBrick).BrickInfo.HorId;
        let ver: number = _brick.getComponent(SingleBrick).BrickInfo.VerId;
        let clear_index: number = _brick.getComponent(SingleBrick).BrickInfo.ClearIndex;

        let middle: number = hor + 1;

        if (this.ReturnClearIndex(hor + 2, ver) == clear_index) {//隔着一个有相同的了
            if (this.ReturnClearIndex(middle, ver - 1) == clear_index) {
                this.TipArray.push(this.BricksArray[middle][ver - 1]);
                return true;
            }
            if (this.ReturnClearIndex(middle, ver + 1) == clear_index) {
                this.TipArray.push(this.BricksArray[middle][ver + 1]);
                return true;
            }
        }

        return false
    }

    /**
     * 纵向第一种判断
     */
    private CheckVer0(_brick: Node): boolean {
        let hor: number = _brick.getComponent(SingleBrick).BrickInfo.HorId;
        let ver: number = _brick.getComponent(SingleBrick).BrickInfo.VerId;
        let clear_index: number = _brick.getComponent(SingleBrick).BrickInfo.ClearIndex;

        let up: number = ver - 1;
        let down: number = ver + 2;

        if (this.ReturnClearIndex(hor, ver + 1) == clear_index) {//纵向两个相同了
            //判断上侧周边有没有
            if (this.ReturnClearIndex(hor, up - 1) == clear_index) {
                this.TipArray.push(this.BricksArray[hor][up - 1]);
                return true;
            }

            if (this.ReturnClearIndex(hor - 1, up) == clear_index) {
                this.TipArray.push(this.BricksArray[hor - 1][up]);
                return true;
            }

            if (this.ReturnClearIndex(hor + 1, up) == clear_index) {
                this.TipArray.push(this.BricksArray[hor + 1][up]);
                return true;
            }

            //判断下侧周边有没有
            if (this.ReturnClearIndex(hor, down + 1) == clear_index) {
                this.TipArray.push(this.BricksArray[hor][down + 1]);
                return true;
            }

            if (this.ReturnClearIndex(hor - 1, down) == clear_index) {
                this.TipArray.push(this.BricksArray[hor - 1][down]);
                return true;
            }

            if (this.ReturnClearIndex(hor + 1, down) == clear_index) {
                this.TipArray.push(this.BricksArray[hor + 1][down]);
                return true;
            }
        }

        return false;
    }

    /**
     * 纵向第二种判断
     */
    private CheckVer1(_brick: Node): boolean {
        let hor: number = _brick.getComponent(SingleBrick).BrickInfo.HorId;
        let ver: number = _brick.getComponent(SingleBrick).BrickInfo.VerId;
        let clear_index: number = _brick.getComponent(SingleBrick).BrickInfo.ClearIndex;

        let middle: number = ver + 1;

        if (this.ReturnClearIndex(hor, ver + 2) == clear_index) {//隔着一个有相同的了
            if (this.ReturnClearIndex(hor - 1, middle) == clear_index) {
                this.TipArray.push(this.BricksArray[hor - 1][middle]);
                return true;
            }
            if (this.ReturnClearIndex(hor + 1, middle) == clear_index) {
                this.TipArray.push(this.BricksArray[hor + 1][middle]);
                return true;
            }
        }

        return false;
    }

    /**
     * 返回他得消除索引
     */
    private ReturnClearIndex(_hor: number, _ver: number): number {
        if (_hor < 0) return -1;
        if (_hor >= GlobalData.HorNum) return -1;
        if (_ver < 0) return -1;
        if (_ver >= GlobalData.VerNum) return -1;
        return this.BricksArray[_hor][_ver].getComponent(SingleBrick).BrickInfo.ClearIndex;

    }

}


